﻿using UnityEngine;

namespace AI.Graph {


    public abstract class SubCondition : CollapsibleNode {

#region Fields

        private static NodeColors s_colors = new NodeColors (new Color32 (255, 170, 120, 255), new Color32 (178, 120, 84, 255), new Color32 (140, 94, 66, 255));

        [SerializeField, HideInInspector]
        [Port (Direction.Input, Capacity.Multi, "Input", typeof (State), typeof (SubCondition))]
        private ConnectionPort m_input = null;

        [SerializeField, HideInInspector]
        [Port (Direction.Output, Capacity.Single, "True", typeof (SubState), typeof (SubCondition))]
        private ConnectionPort m_outputTrue = null;

        [SerializeField, HideInInspector]
        [Port (Direction.Output, Capacity.Single, "False", typeof (SubState), typeof (SubCondition))]
        private ConnectionPort m_outputFalse = null;

#endregion


#region Properties

        internal override NodeColors colors {
            get { return s_colors; }
        }

        public ConnectionPort input {
            get { return m_input; }
            set { m_input = value; }
        }

        public ConnectionPort outputTrue {
            get { return m_outputTrue; }
            set { m_outputTrue = value; }
        }

        public ConnectionPort outputFalse {
            get { return m_outputFalse; }
            set { m_outputFalse = value; }
        }

#endregion


        /// <summary>
        /// Decide which SubState is the next one.
        /// </summary>
        /// <param name="aiBehaviour">The connected AIBehaviour.</param>
        internal void Decide (AIBehaviour aiBehaviour) {
            bool decision = OnDecide (aiBehaviour);
            aiBehaviour.Log (this, $"Decision was: {decision}");

            if (decision) {
                Decide (aiBehaviour, outputTrue.connectedPorts);
            }
            else {
                Decide (aiBehaviour, outputFalse.connectedPorts);
            }
        }


        void Decide (AIBehaviour aiBehaviour, ConnectionPort[] connectedPorts) {
            foreach (ConnectionPort port in connectedPorts) {
                Node node = port.node;

                if (node.IsTypeOf<SubState> ()) {
                    SubState originalSubState = (SubState) node;
                    originalSubState.Perform (aiBehaviour);
                }

                if (node.IsTypeOf<SubCondition> ()) {
                    SubCondition originalSubCondition = (SubCondition) node;
                    originalSubCondition.Decide (aiBehaviour);
                }
            }
        }


        /// <summary>
        /// Check if the condition is true.
        /// </summary>
        /// <param name="aiBehaviour">The connected AIBehaviour.</param>
        /// <returns>Returns true or false depending on the condition.</returns>
        protected abstract bool OnDecide (AIBehaviour aiBehaviour);


        /// <summary>
        /// Deep clone with the given original Node.
        /// </summary>
        internal override void Copy (AIControllerSerializer serializer, Node originalNode) {
            base.Copy (serializer, originalNode);
            SubCondition original = (SubCondition) originalNode;

            m_input = serializer.GetCopyOf (original.m_input);
            m_outputTrue = serializer.GetCopyOf (original.m_outputTrue);
            m_outputFalse = serializer.GetCopyOf (original.m_outputFalse);
        }

    }


}